<script setup>
import {DATA_SCOPE_TYPE, DATA_SCOPE_TYPE_META, DICT_CODE, OPERATE_DRAWER_MODE} from "@/common/constant.js";
import {computed, ref} from "vue";
import {add, detailById, modifyById} from "@/apis/sys/role.js";
import {useUserStore} from "@/store/sys/user.js";
import {useMessage} from "naive-ui";
import {findAllParentIdsById, getTreeAllIds, obj2Array} from "@/utils/index.js";
import {all as allDept} from "@/apis/sys/dept.js";
import DeptTreeSelect from "@/components/dept-tree-select.vue";
import DictSelect from "@/components/dict-select.vue";

onMounted(() => {
  loadDeptList()
})

const message = useMessage();
const userStore = useUserStore()

const formRef = ref(undefined)
const show = defineModel('show')
const props = defineProps({
  mode: {
    type: Number,
    default: OPERATE_DRAWER_MODE.DETAIL
  },
  id: {
    type: String,
    default: undefined
  }
})

const emits = defineEmits(['success'])

const showSubmitBtn = computed(() => {
  return props.mode === OPERATE_DRAWER_MODE.ADD || props.mode === OPERATE_DRAWER_MODE.EDIT
})
const disabled = computed(() => {
  return props.mode === OPERATE_DRAWER_MODE.DETAIL
})
const title = computed(() => {
  if (props.mode === OPERATE_DRAWER_MODE.ADD) {
    return '新增角色'
  } else if (props.mode === OPERATE_DRAWER_MODE.EDIT) {
    return '修改角色'
  } else {
    return '角色详情'
  }
})
const treeData = computed(() => {
  return userStore.getMenuTree
})

const deptList = ref([])
const initFormDataValue = {
  name: undefined,
  dataScope: DATA_SCOPE_TYPE.SELF,
  permission: undefined,
  sort: 1,
  deptIds: [],
  menuIds: [],
  checkedMenuIds: []
}
const formData = ref({...initFormDataValue})
const menuTreeCascade = ref(false)
const loadDeptList = async () => {
  const {code, data} = await allDept()
  if (code === 0) {
    deptList.value = data
  }
}
const onAfterEnter = () => {
  if (props.mode === OPERATE_DRAWER_MODE.DETAIL || props.mode === OPERATE_DRAWER_MODE.EDIT) {
    loadDetail(props.id)
  }
}

const onAfterLeave = () => {
  resetForm()
  menuTreeCascade.value = false
}

const resetForm = () => {
  formData.value = {...initFormDataValue}
};

const loadDetail = async (id) => {
  const {code, data} = await detailById(id)
  if (code === 0) {
    formData.value = data
    formData.value.checkedMenuIds = formData.value.menuIds
  }
}

const onFinish = () => {
  const set = new Set()
  formData.value.checkedMenuIds.forEach(menuId => {
    const parentIds = findAllParentIdsById(userStore.getMenuTree, menuId)
    parentIds.forEach(parentId => set.add(parentId))
  })
  formData.value.menuIds = [...set]
  formRef.value.validate()
      .then(async () => {
        if (props.mode === OPERATE_DRAWER_MODE.ADD) {
          const {code} = await add(formData.value)
          if (code === 0) {
            message.success('新增成功')
            show.value = false
            emits('success')
          }
        } else if (props.mode === OPERATE_DRAWER_MODE.EDIT) {
          const {code} = await modifyById(props.id, formData.value)
          if (code === 0) {
            message.success('修改成功')
            show.value = false
            emits('success')
          }
        }
      })
}

const rules = {
  name: [
    {required: true, message: '请输入角色名称', trigger: 'change'}
  ],
  permission: [
    {required: true, message: '请输入角色编码', trigger: 'blur'}
  ],
  dataScope: [
    {required: true, message: '请选择数据权限', trigger: 'blur'}
  ],
  menuIds: [
    {type: 'array', required: true, message: '请选择数据权限', trigger: 'blur'}
  ]
}

const onMenuTreeSelectAll = (value) => {
  if (value) {
    formData.value.checkedMenuIds = getTreeAllIds(userStore.getMenuTree)
  } else {
    formData.value.checkedMenuIds = []
  }
}

</script>

<template>
  <n-drawer
      v-model:show="show"
      resizable
      :min-width="502"
      :default-width="502"
      @after-enter="onAfterEnter"
      @after-leave="onAfterLeave">
    <n-drawer-content
        :title="title"
        closable
        :native-scrollbar="false">
      <n-form :model="formData" label-placement="left" label-width="80" ref="formRef" :rules="rules">
        <n-form-item label="角色名称" path="name">
          <n-input v-model:value="formData.name" placeholder="请输入" clearable :disabled="disabled"/>
        </n-form-item>
        <n-form-item label="角色编码" path="permission">
          <n-input v-model:value="formData.permission" placeholder="请输入" clearable :disabled="disabled"/>
        </n-form-item>
        <n-form-item label="数据权限" path="dataScope">
          <dict-select :code="DICT_CODE.DATA_SCOPE" v-model:value="formData.dataScope" :disabled="disabled"/>
        </n-form-item>
        <n-form-item label="选择部门" path="deptIds" v-if="formData.dataScope === DATA_SCOPE_TYPE.CUSTOMIZE">
          <dept-tree-select v-model:value="formData.deptIds" :disabled="disabled" multiple/>
        </n-form-item>

        <n-form-item label="排序" path="sort">
          <n-input-number
              v-model:value="formData.sort"
              :min="0" :max="200"
              placeholder="请输入"
              :disabled="disabled"/>
        </n-form-item>
        <n-form-item label="菜单范围" path="checkedMenuIds">
          <n-space vertical>
            <n-space>
              <n-switch @update-value="onMenuTreeSelectAll">
                <template #checked>
                  不选
                </template>
                <template #unchecked>
                  全选
                </template>
              </n-switch>
              <n-switch v-model:value="menuTreeCascade">
                <template #checked>
                  <n-text delete>联级</n-text>
                </template>
                <template #unchecked>
                  联级
                </template>
              </n-switch>
            </n-space>
            <n-tree
                :cascade="menuTreeCascade"
                checkable
                :data="treeData"
                check-strategy="all"
                v-model:checked-keys="formData.checkedMenuIds"
                expand-on-click
                key-field="id"
                label-field="name"
            />
          </n-space>
        </n-form-item>
      </n-form>
      <template #footer>
        <n-space>
          <n-button type="primary" @click="onFinish" v-if="showSubmitBtn">提交</n-button>
          <n-button @click="show = false">取消</n-button>
        </n-space>
      </template>
    </n-drawer-content>
  </n-drawer>
</template>

<style scoped>

</style>